<template>
  <div class="pro-editor">
    <Toolbar
      :editor="editorRef"
      :defaultConfig="toolbarConfig"
      :mode="mode"
      style="border-bottom: 1px solid #ccc"
    />
    <Editor
      :defaultConfig="editorConfig"
      :mode="mode"
      v-model="valueHtml"
      @onCreated="handleCreated"
      @onChange="handleChange"
      style="height: 500px; overflow-y: hidden"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, shallowRef, onBeforeUnmount, watch } from "vue";
import "@wangeditor/editor/dist/css/style.css";
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import type {
  IDomEditor,
  IEditorConfig,
  IToolbarConfig,
} from "@wangeditor/editor";

interface Props {
  modelValue?: string;
  mode?: "default" | "simple";
  height?: string;
  placeholder?: string;
  uploadImgServer?: string;
  uploadImgHeaders?: Record<string, string>;
  uploadImgMaxSize?: number;
  uploadImgMaxNumber?: number;
  disabled?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: "",
  mode: "default",
  height: "500px",
  placeholder: "请输入内容...",
  uploadImgMaxSize: 2 * 1024 * 1024, // 2MB
  uploadImgMaxNumber: 5,
  disabled: false,
});

const emit = defineEmits<{
  (e: "update:modelValue", value: string): void;
  (e: "change", editor: IDomEditor): void;
  (e: "created", editor: IDomEditor): void;
}>();

// 编辑器实例，必须用 shallowRef
const editorRef = shallowRef<IDomEditor>();

// 内容 HTML
const valueHtml = ref(props.modelValue);

// 监听 modelValue 变化
watch(
  () => props.modelValue,
  (val) => {
    if (val !== valueHtml.value) {
      valueHtml.value = val;
    }
  }
);

// 监听内容变化
watch(valueHtml, (val) => {
  emit("update:modelValue", val);
});

// 工具栏配置
const toolbarConfig: Partial<IToolbarConfig> = {
  excludeKeys:
    props.mode === "simple"
      ? ["uploadImage", "insertTable", "codeBlock", "todo"]
      : [],
};

// 编辑器配置
const editorConfig: Partial<IEditorConfig> = {
  placeholder: props.placeholder,
  readOnly: props.disabled,
  MENU_CONF: {
    uploadImage: {
      server: props.uploadImgServer,
      fieldName: "file",
      maxFileSize: props.uploadImgMaxSize,
      maxNumberOfFiles: props.uploadImgMaxNumber,
      headers: props.uploadImgHeaders,
      customInsert(res: any, insertFn: Function) {
        // 从 res 中获取图片地址，根据实际接口返回数据格式修改
        const url = res.data;
        insertFn(url);
      },
    },
  },
};

// 编辑器创建完成时的回调
const handleCreated = (editor: IDomEditor) => {
  editorRef.value = editor;
  emit("created", editor);
};

// 编辑器内容变化时的回调
const handleChange = (editor: IDomEditor) => {
  emit("change", editor);
};

// 组件销毁时，也及时销毁编辑器
onBeforeUnmount(() => {
  const editor = editorRef.value;
  if (editor == null) return;
  editor.destroy();
});

// 暴露方法
defineExpose({
  editor: editorRef,
});
</script>

<style lang="scss">
.pro-editor {
  border: 1px solid #ccc;
  z-index: 100; // 防止被其他元素遮挡

  .w-e-toolbar {
    border: none !important;
    background: #fff !important;
  }

  .w-e-text-container {
    border: none !important;
  }
}

// 深色主题适配
html.dark {
  .pro-editor {
    border-color: #4c4d4f;

    .w-e-toolbar {
      background: #2b2b2b !important;

      .w-e-bar-item button {
        color: #e5eaf3 !important;

        &:hover {
          background-color: #363637 !important;
        }
      }
    }

    .w-e-text-container {
      background-color: #2b2b2b !important;

      .w-e-text {
        color: #e5eaf3 !important;
      }
    }
  }
}
</style>
